package com.imut.lagain.service.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imut.lagain.service.IWeChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.client.RestTemplate;

import javax.crypto.Cipher;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

/**
 * 微信API服务类
 */
@Service
public class WeChatServiceImpl implements IWeChatService {
    private static final Logger log = LoggerFactory.getLogger(WeChatServiceImpl.class);

    
    @Value("${wechat.appid}")
    
        private String appId;
    
    @Value("${wechat.secret}")
    private String appSecret;
    
    @Value("${wechat.api.code2session}")
    private String code2SessionUrl;
    
    @Value("${wechat.api.token:https://api.weixin.qq.com/cgi-bin/token}")
    private String tokenUrl;
    
    @Value("${wechat.token:}")
    private String token;
    
    private final WebClient webClient;
    private final ObjectMapper objectMapper;
    private String cachedAccessToken;
    private long tokenExpireTime;
    
    public WeChatServiceImpl() {
        this.webClient = WebClient.builder().build();
        this.objectMapper = new ObjectMapper();
    }
    
    /**
     * 通过code获取session_key和openid
     * @param code 微信登录code
     * @return 包含session_key和openid的Map
     */
    @Override
    public Map<String, String> getSessionInfo(String code) {
        try {
            String url = code2SessionUrl + "?appid=" + appId + "&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code";
            
            String response = webClient.get()
                    .uri(url)
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
            JsonNode jsonNode = objectMapper.readTree(response);
            
            if (jsonNode.has("errcode")) {
                log.error("WeChat API error: {}", response);
                return null;
            }
            
            Map<String, String> result = new HashMap<>();
            result.put("openid", jsonNode.get("openid").asText());
            result.put("session_key", jsonNode.get("session_key").asText());
            
            if (jsonNode.has("unionid")) {
                result.put("unionid", jsonNode.get("unionid").asText());
            }
            
            return result;
        } catch (Exception e) {
            log.error("Failed to get session info from WeChat", e);
            return null;
        }
    }
    
    /**
     * 解密微信手机号
     * @param encryptedData 加密数据
     * @param iv 初始向量
     * @param sessionKey 会话密钥
     * @return 解密后的手机号信息
     */
    @Override
    public Map<String, Object> decryptPhoneNumber(String encryptedData, String iv, String sessionKey) {
        try {
            byte[] dataByte = Base64.getDecoder().decode(encryptedData);
            byte[] keyByte = Base64.getDecoder().decode(sessionKey);
            byte[] ivByte = Base64.getDecoder().decode(iv);
            
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, spec, ivSpec);
            
            byte[] resultByte = cipher.doFinal(dataByte);
            String result = new String(resultByte, StandardCharsets.UTF_8);
            JsonNode jsonNode = objectMapper.readTree(result);
            Map<String, Object> phoneInfo = new HashMap<>();
            phoneInfo.put("phoneNumber", jsonNode.get("phoneNumber").asText());
            phoneInfo.put("purePhoneNumber", jsonNode.get("purePhoneNumber").asText());
            phoneInfo.put("countryCode", jsonNode.get("countryCode").asText());
            
            return phoneInfo;
        } catch (Exception e) {
            log.error("Failed to decrypt phone number", e);
            return null;
        }
    }
    
    /**
     * 发送订阅消息
     * @param openid 用户openid
     * @param templateId 模板ID
     * @param data 模板数据
     * @param page 跳转页面
     * @return 是否发送成功
     */
    @Override
    public boolean sendSubscribeMessage(String openid, String templateId, Map<String, Object> data, String page) {
        try {
            String accessToken = getAccessTokenInternal();
            if (accessToken == null) {
                log.error("获取access token失败");
                return false;
            }
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("touser", openid);
            requestBody.put("template_id", templateId);
            requestBody.put("page", page);
            requestBody.put("data", data);
            String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            String response = webClient.post()
                    .uri(url)
                    .bodyValue(requestBody)
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
            JsonNode jsonNode = objectMapper.readTree(response);
            int errcode = jsonNode.path("errcode").asInt();
            
            if (errcode == 0) {
                return true;
            } else {
                log.error("订阅消息发送失败: errcode={}, errmsg={}", errcode, jsonNode.path("errmsg").asText());
                return false;
            }
            
        } catch (Exception e) {
            log.error("发送订阅消息异常: openid={}, templateId={}", openid, templateId, e);
            return false;
        }
    }

    /**
     * 检查微信服务是否可用
     * @return 是否可用
     */
    @Override
    public boolean isWeChatServiceAvailable() {
        try {
            String accessToken = getAccessTokenInternal();
            return accessToken != null;
        } catch (Exception e) {
            log.error("检查微信服务可用性失败", e);
            return false;
        }
    }
    
    /**
     * 获取服务状态
     * @return 服务状态
     */
    @Override
    public Map<String, Object> getServiceStatus() {
        Map<String, Object> status = new HashMap<>();
        try {
            boolean available = isWeChatServiceAvailable();
            status.put("available", available);
            status.put("appId", appId != null ? appId.substring(0, Math.min(appId.length(), 8)) + "***" : "null");
            status.put("timestamp", System.currentTimeMillis());
        } catch (Exception e) {
            status.put("error", e.getMessage());
        }
        return status;
    }
    
    /**
     * 获取微信access token
     * @return access token
     */
    private String getAccessTokenInternal() {
        try {
            if (cachedAccessToken != null && System.currentTimeMillis() < tokenExpireTime) {
                return cachedAccessToken;
            }
            String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s", 
                    tokenUrl, appId, appSecret);
            
            String response = webClient.get()
                    .uri(url)
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
            
            if (response != null) {
                JsonNode jsonNode = objectMapper.readTree(response);
                if (jsonNode.has("access_token")) {
                    cachedAccessToken = jsonNode.get("access_token").asText();
                    int expiresIn = jsonNode.get("expires_in").asInt();
                    tokenExpireTime = System.currentTimeMillis() + (expiresIn - 300) * 1000L;
                    return cachedAccessToken;
                } else {
                    log.error("获取access token失败: {}", response);
                    return null;
                }
            }
        } catch (Exception e) {
            log.error("获取access token异常", e);
        }
        return null;
    }
    
    /**
     * 处理微信消息
     * @param request HTTP请求
     * @param response HTTP响应
     */
    @Override
    public void handleMessage(HttpServletRequest request, HttpServletResponse response) {
        try {
            log.info("处理微信消息请求");
            // TODO: 实现微信消息处理逻辑
            response.getWriter().write("success");
        } catch (Exception e) {
            log.error("处理微信消息失败", e);
        }
    }
    
    /**
     * 获取微信访问令牌
     * @return 访问令牌信息
     */
    @Override
    public Map<String, Object> getAccessToken() {
        Map<String, Object> result = new HashMap<>();
        try {
            String accessToken = getAccessTokenInternal();
            if (accessToken != null) {
                result.put("success", true);
                result.put("access_token", accessToken);
                result.put("expires_at", tokenExpireTime);
            } else {
                result.put("success", false);
                result.put("message", "获取访问令牌失败");
            }
        } catch (Exception e) {
            log.error("获取访问令牌异常", e);
            result.put("success", false);
            result.put("message", "获取访问令牌异常: " + e.getMessage());
        }
        return result;
    }
    
    @Override
    public boolean verifySignature(String signature, String timestamp, String nonce) {
        try {
            // 使用微信配置的token进行签名验证
            String[] arr = {token, timestamp, nonce};
            Arrays.sort(arr);
            StringBuilder content = new StringBuilder();
            for (String s : arr) {
                content.append(s);
            }
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            StringBuilder hexStr = new StringBuilder();
            for (byte b : digest) {
                String shaHex = Integer.toHexString(b & 0xFF);
                if (shaHex.length() < 2) {
                    hexStr.append(0);
                }
                hexStr.append(shaHex);
            }
            return hexStr.toString().equals(signature);
        } catch (Exception e) {
            log.error("验证微信签名失败", e);
            return false;
        }
    }
    
    @Override
    public Map<String, Object> sendTemplateMessage(Map<String, Object> messageData) {
        Map<String, Object> result = new HashMap<>();
        try {
            String accessToken = getAccessTokenInternal();
            if (accessToken == null) {
                result.put("success", false);
                result.put("message", "获取访问令牌失败");
                return result;
            }
            
            String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
            
            RestTemplate restTemplate = new RestTemplate();
            @SuppressWarnings("unchecked")
            Map<String, Object> response = restTemplate.postForObject(url, messageData, Map.class);
            
            if (response != null && "0".equals(String.valueOf(response.get("errcode")))) {
                result.put("success", true);
                result.put("message", "模板消息发送成功");
                result.put("msgid", response.get("msgid"));
            } else {
                result.put("success", false);
                result.put("message", "模板消息发送失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            log.error("发送模板消息失败", e);
            result.put("success", false);
            result.put("message", "发送模板消息失败: " + e.getMessage());
        }
        return result;
    }
    
    @Override
    public Map<String, Object> getUserInfo(String openid) {
        Map<String, Object> result = new HashMap<>();
        try {
            String accessToken = getAccessTokenInternal();
            if (accessToken == null) {
                result.put("success", false);
                result.put("message", "获取访问令牌失败");
                return result;
            }
            
            String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid + "&lang=zh_CN";
            
            RestTemplate restTemplate = new RestTemplate();
            @SuppressWarnings("unchecked")
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            
            if (response != null && !response.containsKey("errcode")) {
                result.put("success", true);
                result.put("userInfo", response);
            } else {
                result.put("success", false);
                result.put("message", "获取用户信息失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            result.put("success", false);
            result.put("message", "获取用户信息失败: " + e.getMessage());
        }
        return result;
    }
}

